package com.example.demo.demo.invoke;

import com.example.demo.enums.EmotionScene;
import com.example.demo.enums.ExtractedEntity;
import com.example.demo.enums.NluResult;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对话状态类 (我们的“电子病历”)
 * 它封装了与一个特定用户进行对话的所有上下文信息。
 * 实现 Serializable 接口是为了将来能方便地将其存储到 Redis 等外部会话存储中。
 */
public class DialogueState implements Serializable {

    private static final long serialVersionUID = 1L; // 用于序列化

    private EmotionScene userGoal; // 用户的长期意图
    private final Map<String, Object> accumulatedSlots; // 累积的槽位信息

    public DialogueState() {
        this.accumulatedSlots = new ConcurrentHashMap<>(); // 使用线程安全的Map
    }

    // --- Getters ---
    public EmotionScene getUserGoal() {
        return userGoal;
    }

    public Map<String, Object> getAccumulatedSlots() {
        return Map.copyOf(accumulatedSlots); // 返回一个不可变副本，保证封装性
    }

    public Object getSlot(String slotName) {
        return accumulatedSlots.get(slotName);
    }

    public boolean isSlotFilled(String slotName) {
        return accumulatedSlots.containsKey(slotName) && accumulatedSlots.get(slotName) != null;
    }

    // --- Setters / Updaters ---
    // Setters (用于AI更新)
    public void setUserGoal(EmotionScene userGoal) { this.userGoal = userGoal; }
    public void setAccumulatedSlots(Map<String, Object> slots) {
        this.accumulatedSlots.clear();
        this.accumulatedSlots.putAll(slots);
    }
    /**
     * 这是DST的核心更新逻辑：用NLU的新信息来更新当前状态。
     *
     * @param nluResult 最新一轮NLU的分析结果
     */
    public void updateState(NluResult nluResult) {
        // 1. 更新长期意图 (如果还未设置)
        if (this.userGoal == null || this.userGoal == EmotionScene.UNKNOWN) {
            if (nluResult.scene() != EmotionScene.UNKNOWN) {
                this.userGoal = nluResult.scene();
            }
        }

        // 2. 更新累积的槽位 (只填充之前为空的槽位，避免覆盖)
        for (ExtractedEntity entity : nluResult.entities()) {
            // putIfAbsent: 如果key不存在或值为null，才放入新值。
            // 这是一个简单的更新策略，你可以根据业务需求调整为可覆盖的策略。
            accumulatedSlots.putIfAbsent(entity.type(), entity.value());
        }
    }

    @Override
    public String toString() {
        return "DialogueState{" +
                "userGoal=" + userGoal +
                ", accumulatedSlots=" + accumulatedSlots +
                '}';
    }
}